package org.aurora.client.spring;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.aurora.client.AuroraClient;
import org.aurora.client.AuroraClientConfig;
import org.aurora.client.DefaultAuroraClient;
import org.aurora.client.ITaskProcessor;
import org.aurora.client.spring.acquirer.AuroraTaskAnnotationSpringTaskProcessorAcquirer;
import org.aurora.client.spring.acquirer.TaskProcessorBeanSpringTaskProcessorAcquirer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.*;
import java.util.stream.Collectors;

public class AuroraTaskSpringRegister implements ApplicationContextAware, InitializingBean, DisposableBean {
    private static final Logger log = LoggerFactory.getLogger(AuroraTaskSpringRegister.class);

    private ApplicationContext applicationContext;

    private List<SpringTaskProcessorAcquirer> springTaskAcquirers;

    private Map<String, ITaskProcessor> taskProcessorMap;

    private AuroraClient auroraClient;

    private AuroraClientConfig config;

    @Override
    public void afterPropertiesSet() {
        // 初始化 spring 任务获取器
        this.springTaskAcquirers = initSpringTaskProcessorAcquirer();
        // 获取任务处理器
        this.taskProcessorMap = acquireTaskProcessors();
        // 配置
        this.config = fetchAuroraClientConfig();
        // 新建客户端
        this.auroraClient = new DefaultAuroraClient(this.config, this.taskProcessorMap);
        // 启动客户端
        this.auroraClient.start();
    }

    private AuroraClientConfig fetchAuroraClientConfig() {
        try {
            return this.applicationContext.getBean(AuroraClientConfig.class);
        } catch (NoSuchBeanDefinitionException e) {
            // 使用默认配置
            log.info("AuroraTaskSpringRegister uses default AuroraClientConfig");
            return new AuroraClientConfig();
        }
    }

    private List<SpringTaskProcessorAcquirer> initSpringTaskProcessorAcquirer() {
        return Arrays.asList(
                new AuroraTaskAnnotationSpringTaskProcessorAcquirer(this.applicationContext),    // 从继承 ITaskProcessor 的子类的 bean
                new TaskProcessorBeanSpringTaskProcessorAcquirer(this.applicationContext)       // 实现 @AuroraTask("任务名") 注解的任务
        );

        // todo
        // 使用 xml 标签，注册的 bean ， <aurora-task clazz="类" method="需要被调度的方法" task="任务名"></aurora-task>
        // 服务端通过 class 和方法名指定的任务
    }

    private Map<String, ITaskProcessor> acquireTaskProcessors() {
        if (CollectionUtils.isEmpty(this.springTaskAcquirers)) {
            return Collections.emptyMap();
        }

        List<Map.Entry<String, ITaskProcessor>> taskProcessorEntryList = new ArrayList<>();

        for (SpringTaskProcessorAcquirer springTaskAcquirer : this.springTaskAcquirers) {
            Map<String, ITaskProcessor> taskProcessorMap = springTaskAcquirer.acquirer();

            if (MapUtils.isEmpty(taskProcessorMap)) {
                continue;
            }

            taskProcessorEntryList.addAll(taskProcessorMap.entrySet());
        }

        return taskProcessorEntryList.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void destroy() throws Exception {
        if (this.auroraClient != null) {
            this.auroraClient.stop();
        }
    }
}
